package com.test.drawing;

import com.test.positioning.PositionChangerByPixels;
import com.test.positioning.Projector;

/**
 * Class that holds the Model of a Player
 */
public class PlayerModel implements Touchable, PositionChangerByPixels {

	// Touch Radius
	private static final int RADIUS = 35;

	private static final float DISTANCE_FROM_MESH = 4;

	// Meshes
	private Animation mMesh;
	private BoardMesh mSign;

	// Pixels Coordinates
	private float xp;
	private float yp;

	// Distance (?)
	private double d = 0;

	/**
	 * Class' Constructor
	 * 
	 * @param mesh
	 *            Animation to be Used as Model
	 */
	public PlayerModel(Animation mesh) {
		this.mMesh = mesh;
	}

	/**
	 * Sets the BoardMesh to be Used for this Model
	 * 
	 * @param mesh
	 */
	public void setBoard(BoardMesh mesh) {
		this.mSign = mesh;
	}

	/**
	 * Gets the Animation used by this Model
	 * 
	 * @return Animation
	 */
	public Animation getPlayerMesh() {
		return mMesh;
	}

	/**
	 * Gets the BoardMesh used by this Model
	 * 
	 * @return BoardMesh or null if not Setted
	 */
	public BoardMesh getPlayerBoard() {
		return mSign;
	}

	/**
	 * Sets the Players' Position in Screen Pixels
	 * 
	 * @param x
	 *            x position on screen
	 * @param y
	 *            y position on screen
	 */
	public void setPositionInPixels(float x, float y) {
		xp = x;
		yp = y;
	}

	@Override
	public void updateCoordinatesByPixels(Projector projector) {
//		a = (x2 - x1)
//		b = (y2 - y1)
//		c = (z2 - z1)
//
//		x = at + x1
//		y = bt + y1
//		z = ct + z1
		
		// Get Points from Near and Far Planes
		float[] nearPlane = new float[3];
		projector.unProject(new float[] { xp, yp, 0 }, 0, nearPlane, 0);
		float[] farPlane = new float[3];
		projector.unProject(new float[] { xp, yp, 1 }, 0, farPlane, 0);
		
		float x, y, z;
		
		// Set the Plane to Stop using T Parameter
		float t = (getPlayerMesh().getZ() - nearPlane[0]) / (farPlane[2] - nearPlane[2]);
		
		// Set the Plane here
		x = (farPlane[0] - nearPlane[0]) * t + nearPlane[0];
		y = (farPlane[1] - nearPlane[1]) * t + nearPlane[1];
		z = (farPlane[2] - nearPlane[2]) * t + nearPlane[2];
		
		// Sets the New Position
		setPosition(x, y, getPlayerMesh().getZ());
	}

	/**
	 * Gets the Last Updated Distance from isCollided
	 * 
	 * @return double - Distance
	 */
	public double getDistance() {
		return d;
	}

	/**
	 * Play Player's Animation
	 */
	public void animate() {
		mMesh.playAnimation();
		if (mSign != null)
			mSign.startFading();
	}

	/**
	 * Stop Player's Animation
	 */
	public void stopAnimate() {
		mMesh.stopAnimation();
		if (mSign != null)
			mSign.stopFading();
	}

	/**
	 * Sets Player's Position in Space
	 * 
	 * @param x
	 *            X Coordinate
	 * @param y
	 *            Y Coordinate
	 * @param z
	 *            Z Coordinate
	 */
	public void setPosition(float x, float y, float z) {
//		System.out.println("Pos = " + x + ", " + y + ", " + z);
		mMesh.setPosition(x, y, z);
		if (mSign != null)
			mSign.setPosition(x, y + DISTANCE_FROM_MESH, z);
	}

	/**
	 * Sets the Z Position of this Model
	 * 
	 * @param z
	 *            Position in the Z Axis
	 */
	public void setZ(int z) {
		setPosition(mMesh.getX(), mMesh.getY(), z);
	}

	/**
	 * Set number to be Shown in the Board
	 * 
	 * @param number
	 *            New Number to be Shown
	 */
	public void setBoardNumber(int number) {
		if (mSign != null)
			mSign.setNumber(number);
	}

	@Override
	public boolean isTouched(float x, float y) {
		float[] win = new float[3];

		Projector.getInstance().project(
				new float[] { mMesh.getX(), mMesh.getY(), mMesh.getZ(), 1 }, 0,
				win, 0);

		double distance = Math.sqrt(Math.pow((win[0] - x), 2)
				+ Math.pow((win[1] - y), 2));
		d = distance;
		if (distance <= RADIUS) {
			return true;
		}
		return false;
	}
}
